package com.acme.bankapp.service.network;

import java.io.*;
import java.net.*;

import com.acme.bankapp.domain.bank.*;
import com.acme.bankapp.domain.exception.*;
import com.acme.bankapp.service.bank.*;

/**
 * Class for bank server
 * @author alex
 */
public class BankServer extends BankNetwork {
	private Bank bank;
	
	/**
	 * The main method of class
	 * @param args args the command-line parameters
	 */
	public static void main(String[] args) {
		try {
			(new BankServer()).startServer(new Bank());
		} catch (ListenersMaxException e) {
			System.out.println("Err: Reached the maximum number of listeners!");
		}
	}
	
	/**
	 * Start bank server
	 */
	public void startServer(Bank bank) {
		this.bank = bank;
		while (true) {
			accept();
		}
	}
	
	/**
	 * Accept bank client connection
	 */
	public void accept() {
		try (ServerSocket serverSocket = new ServerSocket(BankNetwork.SERVER_PORT, BankNetwork.SERVER_BACKLOG)) {
			System.out.println("==Server started==");
			try (Socket socket = serverSocket.accept();
					BufferedReader tempReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
					BufferedWriter tempWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
				System.out.println("==Client connected==");
				this.reader = tempReader;
				this.writer = tempWriter;
				String message;
				do {
					message = recieveMessage();
					handle(message);
				} while (!message.equals(BankNetwork.COMMAND_EXIT));
			} catch (IOException e) {
				System.out.println("Err: Network error!");
			}
		} catch (IOException e) {
			System.out.println("Err: Network error!");
		}
	}
	
	/**
	 * Handle bank client command
	 * @param message the message
	 */
	public void handle(String message) {
		if (message == null)
			return;
		switch (message) {
			case BankNetwork.COMMAND_ADD_CLIENT:
				addClient();
				break;
			case BankNetwork.COMMAND_LIST_CLIENTS:
				listClients();
				break;
		}
	}
	
	/**
	 * Adding client to bank
	 */
	public void addClient() {
		String message = recieveMessage();
		try {
			bank.addClient(BankDataLoaderService.parseClient(BankDataLoaderService.parseLine(message)));
			sendMessage("Client added!");
		} catch (ClientsMaxException e) {
			sendMessage("Err: Reached the maximum number of clients!");
		} catch (ClientExistsException e) {
			sendMessage("Err: Client already exists");
		} catch (IllegalArgumentException e) {
			sendMessage("Err: Balance and overdraft can not be negative!");
		} catch (Exception e) {
			sendMessage("Err: Client adding error!");
		}
	}
	
	/**
	 * List clients of bank
	 */
	public void listClients() {
		while (bank.hasNextClient()) {
			sendMessage(bank.getNextClient().toString());
		}
		sendMessage(BankNetwork.COMMAND_STOP);
	}
}
